#ifndef __PROJECT_H__
#define __PROJECT_H__

#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <fstream>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <atomic>
#include <thread>
#include <mutex>
#include <chrono>  // 用于 chrono
#include <condition_variable>
#include <cstring>
using namespace std;

#ifdef __cplusplus
extern "C" 
{
#endif
  #include <stdbool.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/mman.h>
  #include <fcntl.h>
  #include <unistd.h>
  #include <stdlib.h>
  #include <linux/input.h>
  #include <sys/select.h>
  #include <linux/fb.h>
  #include <string.h>  
  #include <stdio.h>
  #include <errno.h>
#ifdef __cplusplus
}
#endif

#define TOUCH_DEV_PATH "/dev/input/event6"
#define LCD_DEV_PATH "/dev/fb0"
// 在 project.h 中（类外）
#define DOUBLE_CLICK_INTERVAL 500
#define DOUBLE_CLICK_DISTANCE 30


enum SwipeDirection
{
  SWIPE_NONE = 0,
  SWIPE_LEFT,
  SWIPE_RIGHT,
  SWIPE_UP,
  SWIPE_DOWN
};

//设备类
class Device
{
  public:
    Device() {}
    Device(string set_dev_path);
    virtual ~Device() 
    {
      if(this->close_dev() == false)
      {
        cout << "设备关闭异常" << endl;
        exit(-1);
      }
    }

    //属性
    string dev_path;
    int fd;
    //行为
    bool open_dev();
    bool close_dev();
};

class Lcd : virtual public Device
{
  public:
    Lcd() {}
    Lcd(string set_lcd_path);
    ~Lcd();

    //属性
    int lcd_width;
    int lcd_height;
    int * mmap_start;

    //行为
    bool mmap_lcd();
    bool display_bmp(const char * bmp_path);
    void clearScreen();
    void drawChar16x16(char c, int x, int y, uint32_t color);
    void drawString16x16(const std::string& str, int x, int y, uint32_t color);
    void displayTime(); // 显示时间
};

class TouchObserver
{
  public:
    //处理点击事件
    virtual void onTouchClick(int x, int y) = 0;
    //处理滑动事件
    virtual void onTouchSwipe(int direction) = 0;
    virtual ~TouchObserver() = default; // 虚析构，确保派生类析构函数被调用
};

class Touch : virtual public Device
{
  private:
    //存储所有订阅触摸事件的观察者
    vector<TouchObserver*> observers;
    mutex mtx; // 用于保护观察者列表的互斥锁
    thread  listener_thread; // 触摸监听线程

    atomic<bool> is_listening{false};

    // 用于记录一次触摸的起始坐标
    bool is_touching = false;
    int start_x = -1, start_y = -1;
    int current_x = -1, current_y = -1;

    // 事件状态共享（用于 Get_Click_Info 和 Get_Swipe_Info）
    enum EventType { NO_EVENT, CLICK, SWIPE } last_event_type = NO_EVENT;
    int last_click_x = -1, last_click_y = -1;
    int last_swipe_dir = SWIPE_NONE;
    mutex event_mutex;
    condition_variable event_cv;
    bool event_ready = false;

  public:
    Touch() {}
    Touch(string set_touch_path);
    ~Touch();
    //属性
    int touch_max_x;
    int touch_max_y;
    int touch_min_x;
    int touch_min_y;
    int present_x;
    int present_y;


    //行为
    void addObserver(TouchObserver* observer);
    void removeObserver(TouchObserver* observer);
    bool Get_Click_Info(int);
    int Get_Swipe_Info(int);
    void notifyClick(int x, int y);
    void notifySwipe(int direction);
    // 启动触摸监听线程（非阻塞）
    void startListening();
    // 停止触摸监听
    void stopListening();
    // 坐标映射函数
    int mapToLcdX(int touch_x);
    int mapToLcdY(int touch_y);
};

// class Album;
// class Album : public TouchObserver, public std::enable_shared_from_this<Album> // 实现观察者接口
// {
//   private:
//     Lcd * lcd; // 通过指针关联Lcd对象，使用lcd功能
//     unique_ptr<vector<string>> photo_paths;
//     vector<string>::iterator present_photo;

//     // 新增：双击判定相关状态
//     int last_click_x = -1;    // 上一次点击的X坐标
//     int last_click_y = -1;    // 上一次点击的Y坐标
//     //clock_t last_click_time = 0; // 上一次点击的时间（毫秒级）
//     static constexpr int DOUBLE_CLICK_INTERVAL = 500; // 双击时间阈值（500ms，可调整）
//     static constexpr int DOUBLE_CLICK_DISTANCE = 30;  // 双击坐标距离阈值（30像素，防止误触）
//     bool is_zoomed = false;   // 当前是否处于放大状态（用于状态切换）
//     bool has_photos = false;  // 新增：标记是否有图片
//     std::chrono::steady_clock::time_point last_touch_time;
//     mutable mutex album_mtx; // 用于保护相册操作的互斥锁
//   public:
//     Album() : lcd(nullptr),
//               photo_paths(std::make_unique<std::vector<std::string>>()),
//               present_photo(photo_paths->begin()),
//               last_touch_time(std::chrono::steady_clock::time_point::min()) // 初始化为最小值
//     {

//     }
//     Album(Lcd * lcd_ptr) 
//     : lcd(lcd_ptr) ,
//     photo_paths{make_unique<vector<string>>()},
//     last_touch_time(std::chrono::steady_clock::time_point::min())
//     {
//       //this->photo_paths = new vector<string>;
//       this->present_photo = this->photo_paths->begin();
//     }
//     ~Album() = default;
//     // {
//     //   delete this->photo_paths;
//     //   //Lcd由外部管理，不需要在Album中释放
//     // }
    
//     bool addPhoto(string photo_path);
//     bool deletePhoto(string photo_path);
//     vector<string>::iterator findPhoto(string photo_path);
//     bool displayPhoto();
//     void onTouchClick(int x, int y) override;
//     void onTouchSwipe(int direction) override;
//     void nextPhoto();
//     void prevPhoto();
//     void displayZoomedPhoto();
// };




class Album : public TouchObserver, 
              public std::enable_shared_from_this<Album>  // ✅ 继承 enable_shared_from_this
{
private:
    Lcd* lcd;
    std::unique_ptr<std::vector<std::string>> photo_paths;
    // std::vector<std::string>::iterator present_photo;
    size_t present_photo_index; // ✅ 使用索引代替迭代器
    // 双击判定相关状态
    int last_click_x = -1;
    int last_click_y = -1;
    // ✅ 移除 clock_t last_click_time，统一用 chrono
    // static constexpr int DOUBLE_CLICK_INTERVAL = 500; // ms
    // static constexpr int DOUBLE_CLICK_DISTANCE = 30;  // pixels
     bool is_zoomed = false;
    bool has_photos = false; // ✅ 初始化放这里也行

    // ✅ 使用 chrono::steady_clock 记录最后触摸时间
    std::chrono::steady_clock::time_point last_touch_time;

    mutable std::mutex album_mtx; // mutable 允许 const 函数加锁

public:
    Album() 
        : lcd(nullptr),
          photo_paths(std::make_unique<std::vector<std::string>>()),
          last_touch_time(std::chrono::steady_clock::time_point::min()) // 初始化为最小值
    {
    }

    Album(Lcd* lcd_ptr)
        : lcd(lcd_ptr),
          present_photo_index(0), // 初始索引为0
          photo_paths(std::make_unique<std::vector<std::string>>()),
          last_touch_time(std::chrono::steady_clock::time_point::min())
    {
//       try
//  {
//         auto test = shared_from_this(); // 测试是否抛异常
//         std::cout << "shared_from_this works!" << std::endl;
//     } catch (const std::bad_weak_ptr& e) {
//         std::cout << "Not yet managed by shared_ptr (normal in constructor)" << std::endl;
//     }
    if (!lcd) {
        std::cerr << "Error: Album constructed with null Lcd pointer!" << std::endl;
        exit(-1);
    }

    if (lcd->mmap_start == nullptr || lcd->mmap_start == (int*)MAP_FAILED) {
        std::cerr << "Error: Lcd not properly mapped!" << std::endl;
        exit(-1);
    }
    }

    // 析构函数（可选）
    ~Album() = default;

    // 接口函数
    bool addPhoto(const string &photo_path);
    bool deletePhoto(const string &photo_path);
    vector<string>::iterator findPhoto(string photo_path);
    bool displayPhoto();
    void onTouchClick(int x, int y) override;
    void onTouchSwipe(int direction) override;
    void nextPhoto();
    void prevPhoto();
    void displayZoomedPhoto();
    void displayThumbnailGrid();
    void drawThumbnailToLcd(const char* bmp_path, int* lcd_pixels,
                               int x_offset, int y_offset,
                               int thumb_width, int thumb_height);
    void displayScaledDownPhoto();
};

class TimeManager {
public:
    static TimeManager& getInstance();
    std::string getCurrentTime(); // 返回 "HH:MM:SS"

private:
    TimeManager() = default;
    ~TimeManager() = default;
    TimeManager(const TimeManager&) = delete;
    TimeManager& operator=(const TimeManager&) = delete;
};

class FontManager {
public:
    static FontManager& getInstance() 
    {
        static FontManager instance;
        return instance;
    }

    bool loadFont(const std::string& fontPath);
    const unsigned char* getCharBitmap(char c); // 返回指向 32 字节点阵数据的指针

private:
    FontManager() = default;
    ~FontManager() = default;
    FontManager(const FontManager&) = delete;
    FontManager& operator=(const FontManager&) = delete;

    std::vector<unsigned char> fontData; // 存储整个 .DZK 文件内容
};
#endif // __PROJECT_H__